package com.csaba.util;

import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.ResourceBundle;

/**
 * This I18NProvider is designed for multi-user environment (such as servlet containers).
 * This provider maintains language for the thread it is running to, and stores DefaultI18NProvider 
 * in a thread local. Whenever the {@link I18N} class is requesting a bundle, this is returned from the
 * thread local.
 * <p> When you are using this, you have to make sure that it is initialized with the appropriate language code
 * (through the setLanguage() method) when the Thread starts, and that the I18NProviderFactory is initialized 
 * with an instance of this provider. For example
 * <code><pre>
 * ...
 * //make sure that the factory is well initialized
 * if ( I18NProviderFactory.getProvider() instanceof DefaultI18NProvider )
 * {
 *   I18NProviderFactory.setProvider( new ThreadLocalProvider() );
 * }
 * 
 * //set the langauge
 * ThreadLocalProvider.setLanguage( getLanguageCode() );
 * </pre></code>
 * <p> Later on in the same thread, you will get the appropriate language specific messages.
 * In case of a servlet container you can add this code to a ServletFilter for example.
 * @see I18N, I18NProviderFactory
 * @author gyenes
 *
 */
public class ThreadLocalProvider implements I18NProvider
{

	/**
	 * This map stores an instance of a DefaultI18NProvider for each language code.  
	 */
	private static Map<String, I18NProvider> providers = new HashMap<String, I18NProvider>();

	private static ThreadLocal<I18NProvider> providerLocal = new ThreadLocal<I18NProvider>()
	{
		@Override
		protected I18NProvider initialValue()
		{
			return new DefaultI18NProvider();
		}

	};

	public static void setLanguage( final String language )
	{
		synchronized ( providers )
		{
			if ( providers.containsKey(language) )
			{
				providerLocal.set(providers.get(language));
			}
			else
			{
				final I18NProvider provider = new DefaultI18NProvider(new Locale(language));
				providers.put(language, provider);
				providerLocal.set(provider);
			}
		}
	}

	@Override
	public ResourceBundle getBundle( final Object namespace )
	{

		return providerLocal.get().getBundle(namespace);
	}

}
